﻿
using System.Collections.Generic;
using UnityEngine;
namespace FrameWorkSong
{
    [System.Serializable]
    public struct DoubleVector2
    {
        public DoubleVector2(double X, double Y) { x = X; y = Y; }
        public double x;
        public double y;
        public static DoubleVector2 operator -(DoubleVector2 a, DoubleVector2 b) { return new DoubleVector2(a.x - b.x, a.y - b.y); }

    }
    [System.Serializable]
    public struct DoubleVector4
    {
        public DoubleVector4(double X, double Y, double Z, double W) { x = X; y = Y; z = Z; w = W; }
        public double x;
        public double y;
        public double z;
        public double w;
        public static DoubleVector4 zero { get => Zero(); }
        public static double distance(DoubleVector4 a, DoubleVector4 b) { return Distance(a,b); }
        public static DoubleVector4 operator +(DoubleVector4 a, DoubleVector4 b) { return new DoubleVector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); }
        public static DoubleVector4 operator /(DoubleVector4 a, double b) { return new DoubleVector4(a.x /b, a.y / b, a.z / b, a.w / b); }
        static DoubleVector4 Zero()
        {
            DoubleVector4 doubleVector4 = new DoubleVector4(0, 0, 0, 0);
            return doubleVector4;
        }
        static double Distance(DoubleVector4 a, DoubleVector4 b)
        {
            return System.Math.Sqrt(DiffeSquare(a.x, b.x) + DiffeSquare(a.y, b.y) + DiffeSquare(a.z, b.z) + DiffeSquare(a.w, b.w));
        }
        static double DiffeSquare(double a, double b)
        {
            return (a - b) * (a - b);
        }
    }
    public class ChangeMatrixUtil
    {
        /// <summary>
        /// 构造变换行列式
        /// </summary>
        /// <param name="T">转换后的点</param>
        /// <param name="O">转换前的点</param>
        /// <param name="Error"></param>
        public ChangeMatrixUtil(List<DoubleVector2> T, List<DoubleVector2> O,double Error)
        {
            List<DoubleVector4> TMatrixs = new List<DoubleVector4>();
            List<DoubleVector4> OMatrixs = new List<DoubleVector4>();
            int length = T.Count;

            TMatrix = GetChangeMatrix(T[0], T[0 + 1], O[0], O[0+ 1]);
            OMatrix = GetChangeMatrix(O[0], O[0 + 1], T[0], T[0 + 1]);
            //for (int i = 0; i < length - 1; i++)
            //{
            //    TMatrixs.Add(GetChangeMatrix(T[i], T[i + 1], O[i], O[i + 1]));
            //    OMatrixs.Add(GetChangeMatrix(O[i], O[i + 1], T[i], T[i + 1]));
            //}
            //TMatrix = MatrixFilter(TMatrixs, Error);
            //OMatrix = MatrixFilter(OMatrixs, Error);
        }
        public DoubleVector4 TMatrix;
        public DoubleVector4 OMatrix;

        #region 求变换行列式
        /// <summary>
        /// 求二维行列式的一行的两个值，用两个点反求
        /// </summary>
        /// <param name="T1">转换后向量1的x或者y</param>
        /// <param name="T2">转换后向量2的x或者y</param>
        /// <param name="M1">转换前向量1</param>
        /// <param name="M2">转换前向量2</param>
        /// <returns></returns>
        DoubleVector2 GetVec(double  T1, double T2, DoubleVector2 O1, DoubleVector2 O2)
        {
            DoubleVector2 vector = new DoubleVector2();
            double BD = ((O2.x * T1) - (T2 * O1.x)) / ((O1.y * O2.x) - (O2.y * O1.x));
            double AC = (T1 - (BD * O1.y)) / O1.x;
            vector.x = AC;
            vector.y = BD;
            return vector;
        }
        /// <summary>
        /// 求变换行列式
        /// </summary>
        /// <param name="T1">转换后向量1</param>
        /// <param name="T2">转换后向量2</param>
        /// <param name="M1">转换前向量1</param>
        /// <param name="M2">转换前向量2</param>
        /// <returns></returns>
        DoubleVector4 GetChangeMatrix(DoubleVector2 T1, DoubleVector2 T2, DoubleVector2 O1, DoubleVector2 O2)
        {
            DoubleVector4 my_Matrix = new DoubleVector4();
            DoubleVector2 AB = GetVec(T1.x, T2.x, O1, O2);
            DoubleVector2 CD = GetVec(T1.y, T2.y, O1, O2);
            my_Matrix.x = AB.x;
            my_Matrix.y = AB.y;
            my_Matrix.z = CD.x;
            my_Matrix.w = CD.y;
            return my_Matrix;
        }
        /// <summary>
        /// 求二项式平均值
        /// </summary>
        /// <param name="ChangeMatrixs"></param>
        /// <param name="Error">误差范围</param>
        /// <returns></returns>
        DoubleVector4 MatrixFilter(List<DoubleVector4> ChangeMatrixs, double Error)
        {
            int length = ChangeMatrixs.Count;
            //二项式累加
            DoubleVector4 allMatrix = DoubleVector4.zero;
            //二项式个数
            int all =0;
            for (int i = 0; i < length; i++)
            { 
                int errorCount = 0;
                for (int j = 0; j < length; j++)
                {
                    //误差判断
                    if (DoubleVector4.distance(ChangeMatrixs[i], ChangeMatrixs[j]) > Error)
                    {
                        //错误加一
                        errorCount++;
                    } 
                }
                //当错误个数小于一半总数时
                if (errorCount< length*0.5f)
                {
                    allMatrix += ChangeMatrixs[i];
                        all++;
                }
              
            }
            return allMatrix / all;
        }
        #endregion

        #region 变换行列式应用
        /// <summary>
        /// 得到变换后的坐标
        /// </summary>
        /// <param name="Vector">变换前向量</param>
        /// <param name="ChangeMatrix">变换行列式</param>
        /// <param name="VecZero">变换后原点坐标</param>
        /// <param name="VecZero">变换前原点坐标</param>
        /// <returns></returns>
        public DoubleVector2 GetChangeVector(DoubleVector2 Vector, DoubleVector4 ChangeMatrix, DoubleVector2  TZero, DoubleVector2 OZero)
        {
            DoubleVector2 OVector2 = Vector - OZero;
            double x = (OVector2.x * ChangeMatrix.x) + (OVector2.y * ChangeMatrix.y)+ TZero.x;
            double y = (OVector2.x * ChangeMatrix.z) + (OVector2.y * ChangeMatrix.w) + TZero.y;
            DoubleVector2 vector = new DoubleVector2(x, y);
            return vector;
        }
        #endregion

    }
   
}

